package cn.itcast.web.shiro;

import cn.itcast.domain.system.Module;
import cn.itcast.domain.system.User;
import cn.itcast.service.system.ModuleService;
import cn.itcast.service.system.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class AuthRealm extends AuthorizingRealm {

  @Autowired
  private UserService userService;

  @Autowired
  private ModuleService moduleService;

  //当subject调用login方法，其实本质上是调用doGetAuthenticationInfo()方法
  //并且doGetAuthenticationInfo方法的token就是login方法传递过来的token。
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    //1. 先从token取出用户输入邮箱与密码
    UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
    String email = usernamePasswordToken.getUsername();
    //2. 根据邮箱去查找用户，如果查找出来的用户为null，我们直接返回null，那么subject对象就会收到UnknownAccountException异常
    User user = userService.findByEmail(email);
    if (user == null) {
      //我们直接返回null，那么subject对象就会收到UnknownAccountException异常
      return null;
    }
    //3. 对比密码,对比密码的这个过程shiro要自己去完成，你只需要把数据库的密码交给shiro即可。
        /*
          参数一：principal  登录成功后返回的对象
          参数二：credentials  当前用户的数据库密码(这里注意不是用户输入密码)
          参数三：realmName   不需要管理
         */
    AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), "");
    return authenticationInfo;
  }
  //授权
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    //1. 获取到登录成功的用户
    User loginUser = (User) principalCollection.getPrimaryPrincipal();
    //2. 查询登录的用户的权限
    List<Module> userModuleList = moduleService.findModuleByUser(loginUser);
    //3. 把用户具备权限添加到AuthorizationInfo对象中，那么该用户就拥有了这些权限。

    //遍历所有的模块，然后把权限添加AuthorizationInfo
    SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    for (Module module : userModuleList) {
      //添加权限的标记。 注意： 这里的标识只要求唯一性， 我们添加的权限标记可以是模块id也可以是name
      authorizationInfo.addStringPermission(module.getName()); //日志管理
    }
    return authorizationInfo;
  }

}
